package com.geeke.common.sequence.service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.geeke.common.persistence.DataEntity;
import com.geeke.common.sequence.dao.SequenceDao;
import com.geeke.common.sequence.entity.Sequence;
import com.geeke.sys.service.CodeRuleService;
import com.geeke.sys.service.CompanyCodeRuleService;
import com.geeke.utils.FreeMarkers;
import com.google.common.collect.Maps;

/**
 * 业务编号Service
 * @author lys
 * @version 2021-04-30
 */
 
@Service("sequenceService")
@Transactional(readOnly = true)
public class SequenceService {

	@Autowired
	private SequenceDao sequenceDao;

	@Autowired
	private CompanyCodeRuleService companyCodeRuleService;
	
	@Autowired 
	private CodeRuleService codeRuleService;

	private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	/**
	 * 获取编号
	 * @param ruleCode    规则代码
	 * @param bizObject	     业务对象
	 * @return
	 */
	@Transactional(readOnly = false)
	public String generate( String ruleCode, DataEntity<?> entity) {
		return generate(null, ruleCode, entity);
	}
	
	/**
	 * 获取编号
	 * @param companyId	       公司Id  公司Id为空时，使用统一的序号
	 * @param ruleCode    规则代码
	 * @param bizObject	     业务对象
	 * @return
	 */
	@Transactional(readOnly = false)
	public String generate(String companyId, String ruleCode, DataEntity<?> entity) {
		String ruleDef = null;
		// 公司id不为空，使用获取公司的编号规则表达式
		if(StringUtils.isNotBlank(companyId)) {
			ruleDef = companyCodeRuleService.getRuleDefByCode(companyId, ruleCode);
		}
		// 公司Id为空，或公司编号规则不存在，获取系统统一的规则表达式
		if(ruleDef == null) {
			ruleDef = codeRuleService.getRuleDefByCode(ruleCode);
		}
		
		if(ruleDef == null) {
			return null;
		}
		
		return doGenerate(ruleCode, ruleDef, entity);
	}
	
	/**
	 * 生成编号
	 * @param ruleCode    规则代码
	 * @param templateString	规则表达式
	 * @param bizObject			业务对象
	 * @return
	 */
	private String doGenerate(String ruleCode, String templateString, DataEntity<?> entity) {
		// 创建日期和更新日期
		String date = simpleDateFormat.format(new Date());
		entity.setCreateDate(date);
		entity.setUpdateDate(date);
		
		Map<String, Object> model = Maps.newHashMap();
		model.put("biz", entity);
		model.put("seq", 0);
		String prefix = FreeMarkers.renderString(templateString, model);
		Sequence sequence = sequenceDao.getByPrefix(ruleCode, prefix);
		if(sequence == null) {
			sequence = insertSeq(ruleCode, prefix);
		}
		
		model.put("seq", sequence.getVal());
		String seqNo = FreeMarkers.renderString(templateString, model);
		
		sequenceDao.nextSeqById(sequence);
		
		return seqNo;
	}
	
	
	private synchronized Sequence insertSeq(String ruleCode, String prefix) {
		Sequence sequence = sequenceDao.getByPrefix(ruleCode, prefix);
		if(sequence == null) {
			sequence = new Sequence();
			sequence.setCode(ruleCode);
			sequence.setPrefix(prefix);
			sequence.preInsert();
			sequenceDao.insert(sequence);
			
			sequence = sequenceDao.getByPrefix(ruleCode, prefix);	// 增加数据库锁
		}
		return sequence;
	}
}